home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks97 / NewsTicker.sit / NewsTicker / source code / WindowStuff / TickerWindowHandler.cp < prev    next >
Text File  |  1997-06-26  |  25KB  |  1,068 lines

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    NewsTicker, my Hack for 1997
  4. #
  5. #    TickerWindowHandler.cp    -    This handles our TSM floating window that shows
  6. #            the scrolling list of news
  7. #
  8. ------------------------------------------------------------------------------*/
  9.  
  10. #include <TextServices.h>
  11. #include <icons.h>
  12.  
  13. #include "TickerGlobals.h"        /* bring in all the #defines and structures for NewsTicker */
  14. #include "TickerWindowHandler.h"
  15. #include "jGNELib.h"
  16. #include "TickerReadHeadlines.h"
  17.  
  18. void DrawMyWindow(WindowPtr aWind, sMyDataPtr    gGlobalsPtr);
  19. pascal Boolean    CalledHandleAnEvent(EventRecord* event, sMyDataPtr    gGlobalsPtr);
  20. void BuildTheRects( sMyDataPtr    gGlobalsPtr );
  21. void PlotTheItems(sMyDataPtr gGlobalsPtr, Rect* therect);
  22.  
  23. static void ShowTheRect(Rect* therect)
  24. {
  25.     Rect    visrect;
  26.     RgnHandle    rgn;
  27.     short        thetitlebarheight = 12;    //size of the title bar of our menu
  28.     
  29.     rgn = GetGrayRgn();
  30.     
  31.     visrect =( *(rgn))->rgnBBox;
  32.     
  33.     if (therect->bottom > visrect.bottom +2)
  34.     {
  35.         OffsetRect(therect, 0, visrect.bottom +2 - therect->bottom );
  36.     }
  37.     if (therect->top < visrect.top + thetitlebarheight)
  38.     {
  39.         OffsetRect(therect, 0, visrect.top + thetitlebarheight - therect->top);
  40.     }
  41.     if (therect->right > visrect.right +2)
  42.     {
  43.         OffsetRect(therect, visrect.right +2 - therect->right, 0);
  44.     }
  45.     if (therect->left < visrect.left - 2)
  46.     {
  47.         OffsetRect(therect, visrect.left - 2 - therect->left, 0);
  48.     }
  49. }
  50.  
  51. static void SetTheClick(DialogPtr d, short whichitem, Boolean theval)
  52. {
  53.     short    dtype;
  54.     Handle    ditem;
  55.     Rect    rview;
  56.     short    itemhit;
  57.  
  58.     GetDialogItem(d,whichitem,&dtype,&ditem,&rview);
  59.     if (theval)
  60.     {
  61.         SetControlValue((ControlHandle)ditem, 1);
  62.     }
  63.     else
  64.     {
  65.         SetControlValue((ControlHandle)ditem, 0);
  66.     }
  67. }
  68.  
  69. static void BlinkButton(DialogPtr theDialog,
  70.                 short btnNumber)
  71. {
  72.     Handle                itemHandle;
  73.     short                itemType;
  74.     Rect                itemRect;
  75.     long                ignoreLong;
  76.     
  77.     GetDialogItem(theDialog, btnNumber, &itemType, &itemHandle, &itemRect);
  78.     HiliteControl((ControlHandle)itemHandle, true);
  79.     Delay(7, &ignoreLong);
  80.     HiliteControl((ControlHandle)itemHandle, false);
  81. }
  82.     
  83. static pascal void MyDialogItem(DialogPtr thedialog, short itemnum)
  84. {
  85.     short    dtype;
  86.     Handle    ditem;
  87.     Rect    rview;
  88.     RgnHandle    temprgn;
  89.  
  90.     GetDialogItem(thedialog,itemnum,&dtype,&ditem,&rview);
  91.     if (itemnum==24)
  92.     {
  93.         MoveTo(rview.left, rview.top);
  94.         LineTo(rview.right-1, rview.top);
  95.         MoveTo(rview.left, rview.top+3);
  96.         LineTo(rview.right-1, rview.top+3);
  97.     }
  98.     if (itemnum==25)
  99.     {
  100.         PenSize(3,3);
  101.         FrameRoundRect(&rview, 16, 16);
  102.         PenSize(1,1);
  103.     }
  104. }
  105.  
  106. static Boolean NoteDialogKey(EventRecord *macEvent,
  107.                             short *itemHit,
  108.                             DialogPtr    pDialog)
  109.     {
  110.     #define kDelay            7
  111.     
  112.     char        theChar;
  113.     Boolean        OKisOK;
  114.     short    itemType;
  115.     ControlHandle    itemHandle;
  116.     Rect    itemRect;
  117.     
  118.     switch (macEvent->message & charCodeMask)
  119.         {
  120.         case 0x03:        // enter key
  121.         case 0x0D:        // return key
  122.             GetDialogItem(pDialog, 1, &itemType, &((Handle)itemHandle), &itemRect);
  123.             if ((*itemHandle)->contrlHilite)
  124.             {
  125.                 macEvent->what = 0;
  126.                 return    false;
  127.             }
  128.             else
  129.             {
  130.                 BlinkButton(pDialog, 1);
  131.                 *itemHit = 1;
  132.                 return true;
  133.             }
  134.         case 0x1B:        // escape key
  135.             BlinkButton(pDialog, 2);
  136.             *itemHit = 2;
  137.             return true;
  138.         default:
  139.             return false;
  140.         }
  141.     }
  142.  
  143. static pascal Boolean NoteDialogEventFilter(DialogPtr pDialog,
  144.                                     EventRecord *macEvent,
  145.                                     short *itemHit)
  146.     {
  147.     switch (macEvent->what)
  148.         {
  149.         case keyDown:
  150.         case autoKey:
  151.             return NoteDialogKey(macEvent, itemHit, pDialog);
  152.         default:
  153.             return false;
  154.         }
  155.     }
  156.  
  157.  
  158. Boolean DoConfigure ( void )
  159. {
  160.     DialogPtr mydialog;
  161.     short    dtype;
  162.     Handle    ditem;
  163.     Rect    rview;
  164.     short    itemhit;
  165.     Point    mypoint;
  166.     
  167.     sPreferences    tempprefs;
  168.     
  169.     Rect    dataBounds;
  170.     Cell    cSize;
  171.     Cell    theCell;
  172.     CursHandle    thewatch;
  173.     short    i;
  174.  
  175.     OSErr    theerr;
  176.     short    refnum;
  177.     long    count;
  178.     short    index;
  179.     Str255    tempstr;
  180.     
  181.     ModalFilterUPP    OurFilterUPP;
  182.     UserItemUPP    OurItemUPP;
  183.     
  184.     OurFilterUPP = NewModalFilterProc(NoteDialogEventFilter);
  185.     OurItemUPP = NewUserItemProc(MyDialogItem);    //outline the OK button
  186.     
  187.     if (gOurGlobals)
  188.     {
  189.         HideWindow(gOurGlobals->gMyWind);
  190.         gOurGlobals->IsWindowShowing = false;
  191.     }
  192.     BlockMove(&gThePrefs, &tempprefs, sizeof(sPreferences));
  193.     
  194.     mydialog=GetNewDialog(130,nil,(WindowPtr)-1);
  195.     SetTheClick(mydialog, 3, tempprefs.hideIfEmpty);
  196.     SetTheClick(mydialog, 4, tempprefs.scrollingSpeed==1);
  197.     SetTheClick(mydialog, 5, tempprefs.scrollingSpeed==2);
  198.     SetTheClick(mydialog, 6, tempprefs.scrollingSpeed==4);
  199.     SetTheClick(mydialog, 7, tempprefs.DoReadApple);
  200.     SetTheClick(mydialog, 8, tempprefs.DoReadCNN);
  201.     SetTheClick(mydialog, 9, tempprefs.DoReadNews);
  202.     SetTheClick(mydialog, 26, tempprefs.JustShowFirstThree);
  203.     
  204.     GetDialogItem(mydialog,24,&dtype,&ditem,&rview);
  205.     SetDialogItem(mydialog,24,dtype,(Handle)OurItemUPP,&rview);
  206.     GetDialogItem(mydialog,25,&dtype,&ditem,&rview);
  207.     SetDialogItem(mydialog,25,dtype,(Handle)OurItemUPP,&rview);
  208.     
  209.     for (index = 0; index<numWebPages; index++)    // copy the entries off
  210.     {
  211.         GetDialogItem(mydialog,10+index,&dtype,&ditem,&rview);
  212.         SetDialogItemText(ditem, tempprefs.WebPageAddress[index]);
  213.     }
  214.     
  215.     InitCursor();
  216.     do
  217.     {
  218.         ModalDialog(OurFilterUPP, &itemhit);
  219.         switch(itemhit)
  220.         {
  221.             case 1:    //save off the text items
  222.                 for (index = 0; index<numWebPages; index++)    // copy the entries off
  223.                 {
  224.                     GetDialogItem(mydialog,10+index,&dtype,&ditem,&rview);
  225.                     GetDialogItemText(ditem, tempprefs.WebPageAddress[index]);
  226.                     if (!tempprefs.WebPageAddress[index][0])
  227.                     {
  228.                         PLstrcpy(tempprefs.WebPageLastDate[index], "\p");
  229.                         tempprefs.WebPageDisplay[index] = false;
  230.                     }
  231.                     else if (!tempprefs.WebPageLastDate[index][0])    //must be a new guy
  232.                     {
  233.                         PLstrcpy(tempprefs.WebPageLastDate[index], "\pNew Entry");
  234.                         tempprefs.WebPageDisplay[index] = true;
  235.                     }
  236.                 }
  237.  
  238.                 break;
  239.             case 3:
  240.                 tempprefs.hideIfEmpty = !tempprefs.hideIfEmpty;
  241.                 SetTheClick(mydialog, 3, tempprefs.hideIfEmpty);
  242.                 break;
  243.             case 4:
  244.             case 5:
  245.             case 6:
  246.                 switch (itemhit)
  247.                 {
  248.                     case 4:
  249.                         tempprefs.scrollingSpeed = 1;
  250.                         break;
  251.                     case 5:
  252.                         tempprefs.scrollingSpeed = 2;
  253.                         break;
  254.                     case 6:
  255.                         tempprefs.scrollingSpeed = 4;
  256.                         break;
  257.                 }
  258.                 SetTheClick(mydialog, 4, tempprefs.scrollingSpeed==1);
  259.                 SetTheClick(mydialog, 5, tempprefs.scrollingSpeed==2);
  260.                 SetTheClick(mydialog, 6, tempprefs.scrollingSpeed==4);
  261.                 break;
  262.             case 7:
  263.                 tempprefs.DoReadApple = !tempprefs.DoReadApple;
  264.                 SetTheClick(mydialog, 7, tempprefs.DoReadApple);
  265.                 break;
  266.             case 8:
  267.                 tempprefs.DoReadCNN = !tempprefs.DoReadCNN;
  268.                 SetTheClick(mydialog, 8, tempprefs.DoReadCNN);
  269.                 break;
  270.             case 9:
  271.                 tempprefs.DoReadNews = !tempprefs.DoReadNews;
  272.                 SetTheClick(mydialog, 9, tempprefs.DoReadNews);
  273.                 break;
  274.             case 26:
  275.                 tempprefs.JustShowFirstThree = !tempprefs.JustShowFirstThree;
  276.                 SetTheClick(mydialog, 26, tempprefs.JustShowFirstThree);
  277.                 break;
  278.         }
  279.     }
  280.     while (itemhit>2);
  281.     DisposeRoutineDescriptor(OurFilterUPP);
  282.     DisposeRoutineDescriptor(OurItemUPP);
  283.     DisposeDialog(mydialog);
  284.     
  285.     if (itemhit==1)
  286.     {
  287.         BlockMove(&tempprefs, &gThePrefs, sizeof(sPreferences));
  288.     
  289.         theerr = FSpCreate(&gPrefsSpec, 'DATA', 'DATA', smSystemScript);
  290.         theerr = FSpOpenDF(&gPrefsSpec, 0, &refnum);
  291.         if (theerr==noErr)
  292.         {
  293.             count = sizeof(gThePrefs);
  294.             theerr = FSWrite(refnum, &count, &gThePrefs);
  295.             theerr = FSClose(refnum);
  296.         }
  297.         
  298.         if (gOurGlobals)
  299.         {
  300.             FillTheHeadlines(gOurGlobals);
  301.             BuildTheRects(gOurGlobals);
  302.             CalcOffsets ( gOurGlobals );
  303.         }
  304.     }
  305.     if (gOurGlobals)
  306.     {
  307.         ShowWindow(gOurGlobals->gMyWind);
  308.         gOurGlobals->IsWindowShowing = true;
  309.     }
  310.     return (itemhit==1);
  311. }
  312.  
  313. static void ScrollLeft ( sMyDataPtr    gGlobalsPtr )
  314. {
  315.     GrafPtr    tempport;
  316.     RgnHandle    updateRgn;
  317.     short        i;
  318.     Rect    RedrawRect;
  319.     short    amountToScroll;
  320.     
  321.     amountToScroll = gThePrefs.scrollingSpeed;
  322.     if (gGlobalsPtr->sCurrentCommentRect.right - gGlobalsPtr->sCurrentCommentRect.left
  323.         > gGlobalsPtr->MsgWidth)
  324.     {
  325.         return;
  326.     }
  327.     GetPort(&tempport);
  328.     SetPort(gGlobalsPtr->gMyWind);
  329.     
  330.     updateRgn = NewRgn();
  331.     ScrollRect(&gGlobalsPtr->sCurrentCommentRect, - amountToScroll, 0, updateRgn);
  332.     InvalRgn(updateRgn);
  333.     DisposeRgn(updateRgn);
  334.     
  335.     RedrawRect =gGlobalsPtr->sCurrentCommentRect;
  336.     RedrawRect.left = RedrawRect.right - amountToScroll;
  337.  
  338.     for (i = 0; i < gGlobalsPtr->MsgCount; i++)
  339.     {
  340.         gGlobalsPtr->theHeadlines[i].leftside -= amountToScroll;
  341.         
  342.         if (gGlobalsPtr->theHeadlines[i].leftside+gGlobalsPtr->theHeadlines[i].width<0)
  343.         {
  344.             gGlobalsPtr->theHeadlines[i].leftside+= (gGlobalsPtr->MsgWidth );
  345.             if (gGlobalsPtr->theHeadlines[i].leftside<RedrawRect.left)
  346.             {
  347.                 RedrawRect.left = gGlobalsPtr->theHeadlines[i].leftside;
  348.             }
  349.         }
  350.     }
  351.     // Assume we just scrolled the little bit and it's all that needs updating
  352.     PlotTheItems(gGlobalsPtr, &RedrawRect);
  353.     
  354.     ValidRect(&RedrawRect);
  355.     SetPort(tempport);
  356.     
  357. }
  358.  
  359. void CalcOffsets ( sMyDataPtr    gGlobalsPtr )
  360. {
  361.     short    i;
  362.     short    currleft = 0;
  363.     short    width = 0;
  364.     
  365.     SetPort(gGlobalsPtr->gMyWind);
  366.     TextSize(9);
  367.     TextFont(applFont);
  368.     TextFace(0);
  369.     
  370.     gGlobalsPtr->MsgWidth = 0;
  371.     for (i = 0; i < gGlobalsPtr->MsgCount; i++)
  372.     {
  373.         gGlobalsPtr->theHeadlines[i].leftside = currleft;
  374.         
  375.         width = StringWidth(gGlobalsPtr->theHeadlines[i].Subject) + 30;
  376.             
  377.         gGlobalsPtr->theHeadlines[i].width = width;
  378.         currleft += width;
  379.         gGlobalsPtr->MsgWidth += width;
  380.     }
  381.     if ((gThePrefs.hideIfEmpty) && (gGlobalsPtr->MsgWidth == 0))
  382.     {
  383.         HideWindow(gGlobalsPtr->gMyWind);
  384.         gGlobalsPtr->IsWindowShowing = false;
  385.     }
  386.     else
  387.     {
  388.         ShowWindow(gGlobalsPtr->gMyWind);
  389.         gGlobalsPtr->IsWindowShowing = true;
  390.     }
  391.     
  392.     //EraseRect(&gGlobalsPtr->gMyWind->portRect);
  393.     InvalRect(&gGlobalsPtr->gMyWind->portRect);
  394. }
  395.  
  396. void    InitWHandler( void )
  397. {
  398.     Handle    h;
  399.     OSErr    theerr;
  400.     short    vref;
  401.     long    dirID;
  402.     short    refnum;
  403.     long    count;
  404.     short    index;
  405.     
  406.     gThePrefs.hideIfEmpty = true;
  407.     gThePrefs.scrollingSpeed = 2;
  408.     SetRect(&gThePrefs.winrect, 0, 0, 0, 0);
  409.     
  410.     gThePrefs.DoReadNews = true;
  411.     gThePrefs.DoReadApple = true;
  412.     gThePrefs.DoReadCNN = true;
  413.     
  414.     for (index=0; index<numWebPages; index++)
  415.     {
  416.         gThePrefs.WebPageAddress[index][0] = 0;    //zero the strings
  417.         gThePrefs.WebPageLastDate[index][0] = 0;
  418.         gThePrefs.WebPageDisplay[index] = false;
  419.     }
  420.     
  421.     gThePrefs.JustShowFirstThree = true;
  422.     
  423.     theerr = FindFolder(kOnSystemDisk, kPreferencesFolderType, false, &vref, &dirID);
  424.     theerr = FSMakeFSSpec(vref, dirID, "\pNewsTicker.prefs", &gPrefsSpec);
  425.     theerr = FSpOpenDF(&gPrefsSpec, 0, &refnum);
  426.     if (theerr==noErr)
  427.     {
  428.         count = sizeof(gThePrefs);
  429.         theerr = FSRead(refnum, &count, &gThePrefs);
  430.         theerr = FSClose(refnum);
  431.     }
  432.     else
  433.     {
  434.         if (!DoConfigure())
  435.             ExitToShell();
  436.     }
  437.     
  438.     InitjGNEProcLib();
  439.     
  440.     gOurGlobals = (sMyDataPtr) NewPtrSysClear(sizeof(sMyData));
  441.     if (!gOurGlobals)
  442.     {
  443.         ExitToShell();
  444.     }
  445.     
  446.     gOurGlobals->gWindowIsMinimized = false;
  447.     gOurGlobals->gDoQuit = false;
  448.     gOurGlobals->MsgToOpen = -1;
  449.     
  450.     InitInternetConfig();
  451.     
  452.     FillTheHeadlines(gOurGlobals);
  453.     
  454.     CreateMyWindow();
  455.     
  456.     HookjGNE((long)&CalledHandleAnEvent, (long)gOurGlobals);
  457.     
  458.     gOurGlobals->WhenToScroll = TickCount();
  459.     
  460. }
  461.  
  462. void    CloseWHandler ( void )
  463. {
  464.     OSErr    anErr;
  465.     short    refnum;
  466.     long    count;
  467.     
  468.     SetPort(gOurGlobals->gMyWind);
  469.     gThePrefs.winrect = gOurGlobals->sPortRect;
  470.     LocalToGlobal( (Point*) (&gThePrefs.winrect.top));
  471.     LocalToGlobal( (Point*) (&gThePrefs.winrect.bottom));
  472.     
  473.     anErr = FSpCreate(&gPrefsSpec, 'DATA', 'DATA', smSystemScript);
  474.     anErr = FSpOpenDF(&gPrefsSpec, 0, &refnum);
  475.     if (anErr==noErr)
  476.     {
  477.         count = sizeof(gThePrefs);
  478.         anErr = FSWrite(refnum, &count, &gThePrefs);
  479.         anErr = FSClose(refnum);
  480.     }
  481.         
  482.     UnHookjGNE();
  483.     anErr = CloseServiceWindow(gOurGlobals->gMyWind);
  484.     gOurGlobals->gMyWind=nil;
  485.     DisposePtr(gOurGlobals->wStorage);
  486.     DisposePtr((Ptr)gOurGlobals);
  487. }
  488.  
  489. void JustHandleWindow( void )
  490. {
  491.     short    whichmsg;
  492.  
  493.     if (!(gOurGlobals->gMyWind))
  494.     {
  495.         return;
  496.     }
  497.     
  498.     if (!gOurGlobals->IsWindowShowing)
  499.     {
  500.         return;
  501.     }
  502.     
  503.     if (gOurGlobals->MsgToOpen!=-1)
  504.     {
  505.         whichmsg = gOurGlobals->MsgToOpen;
  506.         gOurGlobals->MsgToOpen = -1;
  507.         OpenItem(gOurGlobals, whichmsg);
  508.     }
  509.     if ((gOurGlobals->WhenToScroll+2<TickCount() ) && gOurGlobals->IsWindowShowing)
  510.     {
  511.         ScrollLeft(gOurGlobals);
  512.         gOurGlobals->WhenToScroll = TickCount();
  513.     }
  514.     if ((!EmptyRgn(((WindowPeek)(gOurGlobals->gMyWind))->updateRgn))&& gOurGlobals->IsWindowShowing)
  515.     {
  516.         SetZone(SystemZone());
  517.         BeginUpdate(gOurGlobals->gMyWind);
  518.         DrawMyWindow(gOurGlobals->gMyWind, gOurGlobals);
  519.         EndUpdate(gOurGlobals->gMyWind);
  520.         SetZone(ApplicationZone());
  521.     }
  522.     if (gOurGlobals->gDoQuit)
  523.     {
  524.         gDoneFlag = false;
  525.         gOurGlobals->gDoQuit = false;
  526.     }
  527. }
  528.  
  529. static void DoMyZoom(sMyDataPtr gGlobalsPtr)
  530. {
  531.     GrafPtr    window;
  532.     Point    aPoint;
  533.     Rect    visrect;
  534.     RgnHandle    rgn;
  535.     
  536.     gGlobalsPtr->gDoZoom = false;
  537.     
  538.     rgn = GetGrayRgn();
  539.     visrect =( *(rgn))->rgnBBox;
  540.     
  541.     GetPort(&window);
  542.     SetPort(gGlobalsPtr->gMyWind);
  543.     aPoint.h = 0;
  544.     aPoint.v = 0;
  545.     LocalToGlobal(&aPoint);
  546.     if (gGlobalsPtr->gWindowIsMinimized)
  547.     {
  548.         gGlobalsPtr->gWindowIsMinimized = false;
  549.         ShowHide(gGlobalsPtr->gMyWind, false);
  550.         SizeWindow(gGlobalsPtr->gMyWind,
  551.              gGlobalsPtr->sPortRect.right - gGlobalsPtr->sPortRect.left,
  552.              gGlobalsPtr->sPortRect.bottom - gGlobalsPtr->sPortRect.top,
  553.              true);
  554.         if ( aPoint.h-(gGlobalsPtr->sPortRect.right - gGlobalsPtr->sPortRect.left - 100) > visrect.left)
  555.         {
  556.             MoveWindow(gGlobalsPtr->gMyWind,
  557.                 aPoint.h-(gGlobalsPtr->sPortRect.right - gGlobalsPtr->sPortRect.left - 100),
  558.                 aPoint.v,
  559.                 false);
  560.         }
  561.         ShowHide(gGlobalsPtr->gMyWind, true);
  562.         BuildTheRects(gGlobalsPtr);
  563.         CalcOffsets ( gGlobalsPtr );
  564.     }
  565.     else
  566.     {
  567.         gGlobalsPtr->gWindowIsMinimized = true;
  568.         ShowHide(gGlobalsPtr->gMyWind, false);
  569.         SizeWindow(gGlobalsPtr->gMyWind,
  570.              100,
  571.              25,
  572.              true);
  573.         MoveWindow(gGlobalsPtr->gMyWind,
  574.             aPoint.h+(gGlobalsPtr->sPortRect.right - gGlobalsPtr->sPortRect.left - 100),
  575.             aPoint.v,
  576.             false);
  577.         ShowHide(gGlobalsPtr->gMyWind, true);
  578.         BuildTheRects(gGlobalsPtr);
  579.         CalcOffsets ( gGlobalsPtr );
  580.     }
  581.     SetPort(window);
  582. }
  583.  
  584. void PollWHandler (Point    where)
  585. {
  586.     if (!(gOurGlobals->gMyWind))
  587.     {
  588.         return;
  589.     }
  590.     if (gOurGlobals->gDoZoom)
  591.     {
  592.         DoMyZoom(gOurGlobals);
  593.     }
  594.     if (gOurGlobals->gDidResize)
  595.     {
  596.         gOurGlobals->gDidResize = false;
  597.         BuildTheRects(gOurGlobals);
  598.         CalcOffsets ( gOurGlobals );
  599.     }
  600.     
  601.     JustHandleWindow();
  602.     
  603.     MaybeReload(gOurGlobals);
  604. }
  605.  
  606. void BuildTheRects( sMyDataPtr    gGlobalsPtr )
  607. {
  608.     Rect    tempPortrect;
  609.     
  610.     if (!gGlobalsPtr->gWindowIsMinimized)
  611.     {
  612.         gGlobalsPtr->sPortRect = gGlobalsPtr->gMyWind->portRect;
  613.         
  614.         gGlobalsPtr->sGrowRect.left = gGlobalsPtr->sPortRect.right-5;
  615.         gGlobalsPtr->sGrowRect.right = gGlobalsPtr->sPortRect.right;
  616.         gGlobalsPtr->sGrowRect.top = gGlobalsPtr->sPortRect.bottom - 5;
  617.         gGlobalsPtr->sGrowRect.bottom = gGlobalsPtr->sPortRect.bottom;
  618.     }
  619.     else
  620.     {
  621.         SetRect(&gGlobalsPtr->sGrowRect, 0, 0, 0, 0);
  622.     }            
  623.     tempPortrect = gGlobalsPtr->gMyWind->portRect;
  624.     
  625.     gGlobalsPtr->sCurrentCommentRect.left = tempPortrect.left+8;
  626.     gGlobalsPtr->sCurrentCommentRect.top = 
  627.         (tempPortrect.top + tempPortrect.bottom) / 2 -8;
  628.     gGlobalsPtr->sCurrentCommentRect.bottom = gGlobalsPtr->sCurrentCommentRect.top+16;
  629.     gGlobalsPtr->sCurrentCommentRect.right = tempPortrect.right-8;
  630.     
  631. }
  632.  
  633. void CreateMyWindow ( void )
  634. {
  635.     OSErr    anErr;
  636.     WindowPtr    thewindow;
  637.     Rect    therect;
  638.     Handle    h;
  639.     Str255    tempstr;
  640.     
  641.     gOurGlobals->gMyWind = nil;
  642.     if (!(gOurGlobals->gMyWind))
  643.     {
  644.         SetZone(SystemZone());
  645.         
  646.         if (EmptyRect(&gThePrefs.winrect))
  647.         {
  648.             h = GetResource('WIND', 128);
  649.             if (!h)
  650.             {
  651.                 return;
  652.             }
  653.             BlockMove(*h, &therect, sizeof(therect));
  654.         }
  655.         else
  656.         {
  657.             therect = gThePrefs.winrect;
  658.         }
  659.         ShowTheRect(&therect);
  660.         
  661.         gOurGlobals->wStorage = NewPtr(sizeof(WindowRecord));
  662.         if (!gOurGlobals->wStorage) return;
  663.         
  664.         if (GetResource('WDEF', 124))
  665.         {
  666.             anErr = NewServiceWindow(gOurGlobals->wStorage, &therect,"\pNewsTicker",
  667.                 true,124*16+5,(WindowPtr)-1,true,
  668.                 nil,/*(ComponentInstance)kCurrentProcess*/ &thewindow);
  669.         }
  670.         else
  671.         {
  672.             anErr = NewServiceWindow(gOurGlobals->wStorage, &therect,"\pNewsTicker",
  673.                 true,zoomNoGrow /*floatZoomProc*/, (WindowPtr)-1,true,
  674.                 nil,/*(ComponentInstance)kCurrentProcess*/ &thewindow);
  675.         }
  676.         SetPort(thewindow);
  677.         gOurGlobals->gMyWind = thewindow;
  678.         HiliteWindow(thewindow,true);
  679.         BuildTheRects(gOurGlobals);
  680.         CalcOffsets(gOurGlobals);
  681.         
  682.         SetZone(ApplicationZone());
  683.     }
  684. }
  685.  
  686. void    CloseMyWindow (WindowPtr aWind)
  687. {
  688.     CloseWindow(aWind);
  689. }
  690.  
  691. static void MyTETextBox(unsigned char* thetext, long textlength, Rect* therect, short thejust)
  692. {
  693.     FontInfo info;
  694.     short fontheight;
  695.     short y;
  696.     short rectwidth;
  697.     short length2;
  698.     short theoffset = 0;
  699.     char  thechar;
  700.     Boolean    endofline;
  701.     short lastspace;
  702.     
  703.     GetFontInfo(&info);
  704.     fontheight = info.ascent+info.descent+info.leading;
  705.     y = therect->top+info.ascent;
  706.     rectwidth = therect->right - therect->left;
  707.     do
  708.     {
  709.         if (theoffset>=textlength)
  710.         {
  711.             return;
  712.         }
  713.         length2 = 0;
  714.         endofline = false;
  715.         lastspace = 0;
  716.         do
  717.         {
  718.             thechar = *(Ptr)((long)thetext+theoffset+length2);
  719.             if (thechar==' ')
  720.             {
  721.                 lastspace = length2;
  722.             }
  723.             if (thechar==13)//end of line
  724.             {
  725.                 endofline = true;
  726.             }
  727.             length2++;
  728.         }
  729.         while ((TextWidth(thetext, theoffset, length2)<rectwidth) && (!endofline) && (length2+theoffset<textlength));
  730.         if ((lastspace>0) && (TextWidth(thetext, theoffset, length2)>=rectwidth))
  731.         {
  732.             length2 = lastspace;
  733.         }
  734.         MoveTo(therect->left, y);
  735.         DrawText(thetext, theoffset, length2);
  736.         theoffset += length2;
  737.         y+=fontheight;
  738.     }
  739.     while ((theoffset < textlength) && ( y<therect->bottom));
  740.     if (theoffset<textlength)
  741.     {
  742.         DrawChar('…');
  743.     }
  744. }
  745.  
  746. static void PlotColorPtr(short wDepth, short wFaceSize,
  747.     Rect* DestRect, Ptr p)
  748. {
  749.     PixMapHandle    hPixMap;
  750.     GrafPtr    pCurPort;
  751.  
  752.     wDepth=8; wFaceSize=16;
  753.     
  754.     hPixMap=NewPixMap();
  755.     MoveHHi((Handle)hPixMap);
  756.     HLock((Handle)hPixMap);
  757.     
  758.     (**hPixMap).hRes=0x0480000;
  759.     (**hPixMap).vRes=0x0480000;
  760.     (**hPixMap).pixelType=0;
  761.     (**hPixMap).planeBytes=0;
  762.     (**hPixMap).bounds.top=0;
  763.     (**hPixMap).bounds.left=0;
  764.     (**hPixMap).bounds.bottom=wFaceSize;
  765.     (**hPixMap).bounds.right=wFaceSize;
  766.     (**hPixMap).pixelSize=wDepth;
  767.     (**hPixMap).cmpCount=wDepth;
  768.     (**hPixMap).rowBytes=((wDepth*wFaceSize) / 8)+0x08000;
  769.     (**hPixMap).baseAddr=(Ptr)p;
  770.     
  771.     DisposeCTable((**hPixMap).pmTable);
  772.     (**hPixMap).pmTable=GetCTable(wDepth);
  773.     
  774.     GetPort(&pCurPort);
  775.     CopyBits((BitMap*)(*hPixMap), &(pCurPort->portBits), &(**hPixMap).bounds,
  776.         DestRect,srcCopy,nil);
  777.     (**hPixMap).baseAddr=nil;
  778.     HUnlock((Handle)hPixMap);
  779.     DisposePixMap(hPixMap);
  780. }
  781.  
  782. /* Define TopLeft and BotRight macros for convenience. Notice the implicit
  783.    dependency on the ordering of fields within a Rect */
  784. #define TopLeft(aRect)    (* (Point *) &(aRect).top)
  785. #define BotRight(aRect)    (* (Point *) &(aRect).bottom)
  786.  
  787. static short ColorRectDepth(Rect* therect)
  788. {
  789.     long    response;
  790.     Rect    r2;
  791.     GDHandle    thegd;
  792.     
  793.     if (Gestalt(gestaltQuickdrawVersion,&response)==noErr)
  794.     {
  795.         if (response>=gestalt8BitQD)
  796.         {
  797.             r2 = *therect;
  798.             LocalToGlobal((Point*)(&r2.top));
  799.             LocalToGlobal((Point*)(&r2.bottom));
  800.             thegd = GetMaxDevice(&r2);
  801.             if (thegd)
  802.             {
  803.                 return (**(**thegd).gdPMap).pixelSize;
  804.             }
  805.         }
  806.     }
  807.     return 1;  //assume black and white
  808. }
  809.  
  810. static void PlotBWPtr(short wFaceSize,
  811.     Rect* DestRect, Ptr p)
  812. {
  813.     GrafPtr    pCurPort;
  814.     BitMap    mybitmap;
  815.     
  816.     mybitmap.bounds.top = 0;
  817.     mybitmap.bounds.left = 0;
  818.     mybitmap.bounds.bottom = wFaceSize;
  819.     mybitmap.bounds.right = wFaceSize;
  820.     mybitmap.rowBytes = wFaceSize / 8;
  821.     mybitmap.baseAddr = p;
  822.     GetPort(&pCurPort);
  823.     CopyBits(&mybitmap, &(pCurPort->portBits), &mybitmap.bounds, DestRect, 0, nil);
  824. }
  825.  
  826. void PlotTheItems(sMyDataPtr gGlobalsPtr, Rect* therect)
  827. {
  828.     short    i;
  829.     short    leftedge;
  830.     short    rightedge;
  831.     CIconHandle    theicon = nil;
  832.     Rect    temprect;
  833.     
  834.     if (therect->left < gGlobalsPtr->sCurrentCommentRect.left)
  835.     {
  836.         therect->left=gGlobalsPtr->sCurrentCommentRect.left;
  837.     }
  838.     ClipRect(therect);
  839.     EraseRect(therect);
  840.     for (i = 0; i < gGlobalsPtr->MsgCount; i++)
  841.     {
  842.         leftedge = gGlobalsPtr->sCurrentCommentRect.left + gGlobalsPtr->theHeadlines[i].leftside;
  843.         rightedge = leftedge + gGlobalsPtr->theHeadlines[i].width;
  844.         
  845.         if ( ( leftedge < therect->right ) &&
  846.             ( rightedge > therect->left ) )
  847.         {
  848.             if ( leftedge+20 > therect->left ) // Only plot icon if it'll show
  849.             {
  850.                 
  851.                 theicon = GetCIcon(gGlobalsPtr->theHeadlines[i].cicnResID);
  852.                 if (theicon)
  853.                 {
  854.                     temprect.left = leftedge;
  855.                     //temprect.right = leftedge+16;
  856.                     
  857.                     temprect.right = leftedge+ (**theicon).iconBMap.bounds.right - (**theicon).iconBMap.bounds.left;
  858.                     
  859.                     temprect.bottom = (*therect).bottom;
  860.                     temprect.top = (*therect).bottom-16;
  861.                     PlotCIcon(&temprect, theicon);
  862.                     DisposeCIcon(theicon);
  863.                 }
  864.             }
  865.             MoveTo(leftedge+22, (*therect).bottom-4);
  866.             DrawString(gGlobalsPtr->theHeadlines[i].Subject);
  867.         }
  868.     }
  869.     ClipRect(&gGlobalsPtr->gMyWind->portRect);
  870. }
  871.  
  872. void    DrawMyWindow(WindowPtr aWind, sMyDataPtr    gGlobalsPtr)
  873. {
  874.     RGBColor    tempcolor;
  875.     RgnHandle    temprgn;
  876.     Rect    temprect;
  877.     short    h;
  878.     GrafPtr    tempport;
  879.     CIconHandle    theicon = nil;
  880.     Str255    tempstr = "\pNot logged in";
  881.     
  882.     short    leftedge;
  883.     short    rightedge;
  884.     short    i;
  885.     PicHandle    aPicH;
  886.     
  887.     GetPort(&tempport);
  888.     SetPort(aWind);
  889.     ClipRect(&aWind->portRect);
  890.     
  891.     if (ColorRectDepth(&aWind->portRect)<8) //determine what kind of gray to use
  892.     {
  893.         FillRect(&aWind->portRect,&qd.gray);
  894.     }
  895.     else
  896.     {
  897.         aPicH = GetPicture(129);
  898.         DrawPicture(aPicH, &aWind->portRect);
  899.     }
  900.     
  901.     TextSize(9);
  902.     TextFont(applFont);
  903.     TextFace(0);
  904.     
  905.     temprect = gGlobalsPtr->sCurrentCommentRect;
  906.     InsetRect(&temprect, -1, -1);
  907.     FrameRect(&temprect);
  908.     InsetRect(&temprect, 1, 1);
  909.     
  910.     PlotTheItems(gGlobalsPtr, &temprect);
  911.     
  912.     PaintRect(&gGlobalsPtr->sGrowRect);
  913.  
  914.     SetPort(tempport);
  915.         
  916. }
  917.  
  918. static long abs(long theval)
  919. {
  920.     if (theval<0)
  921.     {
  922.         return - theval;
  923.     }
  924.     else
  925.     {
  926.         return theval;
  927.     }
  928. }
  929.  
  930. static void MyClick(Point where, sMyDataPtr gGlobalsPtr)
  931. {
  932.     Rect    temprect;
  933.     Point    thespot;
  934.     long    aLong;
  935.     short    i;
  936.     short    leftedge;
  937.     short    rightedge;
  938.     unsigned long    now;
  939.     
  940.     SetPort(gGlobalsPtr->gMyWind);
  941.     thespot = where;
  942.     GlobalToLocal(&thespot);
  943.     if (PtInRect(thespot, &gGlobalsPtr->sGrowRect))
  944.     {
  945.         SetRect(&temprect, 65, 25, 32767, 25);
  946.         aLong = GrowWindow(gGlobalsPtr->gMyWind, where, &temprect);
  947.         SizeWindow(gGlobalsPtr->gMyWind,
  948.              LoWord(aLong),  HiWord(aLong),  true);
  949.         gGlobalsPtr->gDidResize = true;
  950.     }
  951.     else if (PtInRect(thespot, &gGlobalsPtr->sCurrentCommentRect))
  952.     {
  953.         for (i = 0; i < gGlobalsPtr->MsgCount; i++)
  954.         {
  955.             leftedge = gGlobalsPtr->sCurrentCommentRect.left + gGlobalsPtr->theHeadlines[i].leftside;
  956.             rightedge = leftedge + gGlobalsPtr->theHeadlines[i].width;
  957.             
  958.             if ((thespot.h>leftedge)&&(thespot.h<rightedge))
  959.             {
  960.                 GetDateTime(&now);
  961.                 if ((now - gGlobalsPtr->WhenLastClick>GetDblTime())
  962.                     || ( abs(gGlobalsPtr->LastClick.h-thespot.h)>4)
  963.                     || ( abs(gGlobalsPtr->LastClick.v-thespot.v)>4))
  964.                 {
  965.                     gGlobalsPtr->LastClick = thespot;
  966.                     gGlobalsPtr->WhenLastClick = now;
  967.                     return;
  968.                 }
  969.                 else gGlobalsPtr->MsgToOpen = i;
  970.             }
  971.         }
  972.     }
  973. }
  974.  
  975. typedef pascal long (*GNEHandlerActionProcPtr)(short varCode, WindowRef theWindow,
  976.      short message, Point where);
  977.  
  978. #if GENERATINGCFM    
  979.     enum 
  980.         {
  981.         uppMyWindowDefProcInfo = kPascalStackBased
  982.             | RESULT_SIZE(SIZE_CODE(sizeof(long)))
  983.             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  984.             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
  985.             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(short)))
  986.             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  987.         };
  988.     typedef UniversalProcPtr WindowHandlerUPP;
  989.     #define NewWindowHandlerUPP(userRoutine)    \
  990.         (WindowHandlerUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppMyWindowDefProcInfo, (ISAType)kM68kISA)
  991.     #define CallWindowHandlerProc(userRoutine, param1, param2, param3, param4)    \
  992.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppMyWindowDefProcInfo, param1, param2, param3, param4)
  993. #else
  994.     typedef GNEHandlerActionProcPtr WindowHandlerUPP;
  995.     #define NewWindowHandlerUPP(userRoutine)            ((WindowHandlerUPP) (userRoutine))
  996.     #define CallWindowHandlerProc(userRoutine, param1, param2, param3, param4)    \
  997.         (*(userRoutine)) ((param1), (param2), (param3), (param4))
  998. #endif
  999.  
  1000. static short CheckOneWindow(WindowPtr thewindow, Point where)
  1001. {
  1002.     Handle    h;
  1003.     short    thevariant;
  1004.     short    theresult;
  1005.     WindowHandlerUPP thehandler;
  1006.     
  1007.     h = ((WindowPeek)thewindow)->windowDefProc;
  1008.     HLock(h);
  1009.     
  1010.     thevariant = GetWVariant(thewindow);
  1011.     thehandler = NewWindowHandlerUPP(*(GNEHandlerActionProcPtr)(*h));
  1012.     theresult = CallWindowHandlerProc(thehandler, thevariant, thewindow, wHit, where);
  1013.     DisposeRoutineDescriptor(thehandler);
  1014.     HUnlock(h);
  1015.     return theresult;
  1016. }
  1017.  
  1018. pascal Boolean    CalledHandleAnEvent(EventRecord* event, sMyDataPtr    gGlobalsPtr)
  1019. {
  1020.     short        part;
  1021.     Boolean        hit;
  1022.     Rect        temprect;
  1023.     GrafPtr        savePort;
  1024.  
  1025.     switch ( event->what ) 
  1026.     {
  1027.         case mouseDown:
  1028.             part = CheckOneWindow(gGlobalsPtr->gMyWind, event->where);
  1029.             switch ( part ) {
  1030.                 case wInContent:
  1031.                     GetPort(&savePort);
  1032.                     MyClick(event->where, gGlobalsPtr);
  1033.                     SetPort(savePort);
  1034.                     event->what = 0;
  1035.                     return true;
  1036.                     break;
  1037.                 case wInDrag:                /* pass screenBits.bounds to get all gDevices */
  1038.                     SetRect(&temprect, -32767, -32767, 32767, 32767);
  1039.                     DragWindow(gGlobalsPtr->gMyWind, event->where, &temprect);
  1040.                     event->what = 0;
  1041.                     return true;
  1042.                     break;
  1043.                 case wInGoAway:
  1044.                     hit = TrackGoAway(gGlobalsPtr->gMyWind, event->where);
  1045.                     if (hit )
  1046.                     {
  1047.                         gGlobalsPtr->gDoQuit = true;
  1048.                     }
  1049.                     event->what = 0;
  1050.                     return true;
  1051.                     break;
  1052.                 case wInZoomIn:
  1053.                 case wInZoomOut:
  1054.                     hit =  TrackBox(gGlobalsPtr->gMyWind, event->where ,part+2);
  1055.                     if (hit)
  1056.                     {
  1057.                         gGlobalsPtr->gDoZoom = true;
  1058.                     }
  1059.                     event->what = 0;
  1060.                     return true;
  1061.                     break;
  1062.             }
  1063.             break;
  1064.     }
  1065.     return false;
  1066. }
  1067.  
  1068.